package communication.client.vertx.service;

import communication.client.vertx.config.MyLocalServerAutoConfig;
import communication.client.vertx.config.MyRemoteServerAutoConfig;
import communication.common.business.base.FcrSocketAddress;
import communication.common.business.base.MsgData;
import communication.common.business.hole.P2pHoleRequest;
import communication.common.business.util.MsgDataUtil;
import communication.common.vertx.net.NetManager;
import io.vertx.core.Future;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;


/**
 * 处理client的打洞
 * @author mac
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ClientHoleService {

    private final MyLocalServerAutoConfig localServerAutoConfig;

    private final MyRemoteServerAutoConfig remoteServerAutoConfig;

    private final NetManager netManager;

    /**
     * 监听指定的端口，为打洞做准备
     * @return
     */
    private Future listenPort(){
        FcrSocketAddress localAddress = new FcrSocketAddress(localServerAutoConfig.getHost(), localServerAutoConfig.getPort());
        return netManager.createDefaultUdpServerFuture(localAddress).future();
    }



    /**
     * 根据type判断是预打洞还是打洞，（0-预打洞，1-打洞）
     * 1. 如果是预打洞，则向 receiveDevice 发送一个请求,如果发送成功，则修改request中的数据为打洞用，然后发送给server
     * 2. 如果是打洞，则向 redeviceDevice发送请求，如果成功，则打洞成功。
     */
    public void hole(P2pHoleRequest request){
        log.info("接收到hole请求 request:{}",request);
        switch (request.getType()){
            // 预打洞
            case 0:
                preHole(request);
                break;
            // 打洞
            case 1:
                doHole(request);
        }
    }

    private void doHole(P2pHoleRequest request) {
        // todo:
//        String[] address= request.getReceiveDevice().split(":");
//        sendHello(address[0],Integer.valueOf(address[1]))
//        .onSuccess(e->{
//            log.info("打洞成功！！！！ remote:{} ",request.getReceiveDevice());
//        });

    }

    private void preHole(P2pHoleRequest request) {
        String[] address= request.getReceiveDevice().split(":");
        // 检查是否启动server
        // todo:
//        if(netManager.getDatagramSocket()==null){
//            // 启动server，发送消息
//            CompositeFuture.all(listenPort(),sendHello(address[0],Integer.valueOf(address[1])), noticeHole(request))
//                    .onSuccess(e->{
//                        log.info("预打洞准备完成！address:{}",request.getReceiveDevice());
//            });
//        }else {
//            CompositeFuture.all(sendHello(address[0],Integer.valueOf(address[1])), noticeHole(request))
//                    .onSuccess(e->{
//                        log.info("预打洞准备完成！address:{}",request.getReceiveDevice());
//                    });
//        }

    }

    private P2pHoleRequest reverseHoleRequest(P2pHoleRequest  request){
        request.setType(1);
        Long tmpUserId=request.getTargetUserId();
        request.setTargetUserId(request.getSourceUserId());
        request.setSourceUserId(tmpUserId);
        request.setReceiveDevice(localServerAutoConfig.getAddress());
        return  request;
    }



    // todo:
    private void noticeHole(P2pHoleRequest request) throws Exception {
        MsgData msgData = MsgDataUtil.createHoleRequest(reverseHoleRequest(request));
        FcrSocketAddress remoteSocketAddress = new FcrSocketAddress(remoteServerAutoConfig.getHost(), remoteServerAutoConfig.getPort());
        netManager.sendMsgDataByUdpServer(msgData ,remoteSocketAddress,null);
    }

    public void sendHello(String host,Integer port) throws Exception {
        FcrSocketAddress remoteSocketAddress = new FcrSocketAddress(host, port);
        netManager.sendMsgDataByUdpServer(MsgDataUtil.createLoginMsgData() ,remoteSocketAddress,null);
    }

}
